package JDBC.Pool;

import org.slf4j.LoggerFactory;
import org.slf4j.Logger;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;

//final修饰的类不能被继承
public final class DBConnectionPool extends Pool {
//    private Logger logger = LoggerFactory.getLogger(DBConnectionPool.class);
    private Vector<Connection> freeConnections = new Vector<Connection>();//存放产生的连接对象容器

    private String url = null;//连接字符串
    private String username = null;//用户名
    private String password = null;//密码

    private int numTotal;//连接总数
    private static int numFree = 0;//空闲的连接数, 放入到连接池里的连接数量
    private static int numActive = 0;//在活跃的连接数，默认为0，指的是在使用的线程数量

    private static DBConnectionPool dbConnectionPool = null;//连接池实例对象

    private DBConnectionPool(){
        try{
            init();
            for(int i=0;i<stayConnection;i++){
                Connection c = newConnection();
                if(null != c){
                    freeConnections.addElement(c);
                    numTotal++;
                    numFree++;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    // 使用单例模式获取连接池
    public static DBConnectionPool getInstance() {
        if (dbConnectionPool == null){
            synchronized (Pool.class){
                if(dbConnectionPool == null){
                    dbConnectionPool = new DBConnectionPool();
                }
            }
        }
        return dbConnectionPool;
    }

    /**
     * @Author cgw
     * @Description 初始化
     * @return: void
     * @Date  2022/2/18 16:22
     **/
    private void init() throws Exception{
        InputStream is = DBConnectionPool.class.getClassLoader().getResourceAsStream(propertiesName);
        Properties properties = new Properties();
        properties.load(is);
        this.driverName = properties.getProperty("driverClassName");
        this.url = properties.getProperty("url");
        this.username = properties.getProperty("username");
        this.password = properties.getProperty("password");
    }

    /**
     * @Author cgw
     * @Description 创建一个新连接
     * @return: java.sql.Connection
     * @Date  2022/2/18 16:26
     **/
    private Connection newConnection(){
        Connection connection = null;
        try{
            if(username == null || password == null){
                connection = DriverManager.getConnection(url);
            }else {
                connection = DriverManager.getConnection(url,username,password);
            }
//            logger.info("连接池创建一个新的连接");
        } catch (Exception e) {
//            logger.info("无法创建url:{}的连接，错误原因:{}",url,e);
            return null;
        }
        return connection;
    }

    /**
     * @Author cgw
     * @Description 获取一个可用连接
     * @return: java.sql.Connection
     * @Date  2022/2/18 19:14
     **/
    public synchronized  Connection getConnection() {
        Connection connection = null;
        if(freeConnections.size() > 0){
            connection = (Connection)freeConnections.firstElement();
            numFree--;
            freeConnections.removeElementAt(0);
            try{
                if(connection.isClosed()){
//                    logger.info("从连接池删除一个无效连接");
                    numTotal--;
                    connection = getConnection();
                }
            } catch (Exception e) {
//                logger.info("从连接池删除一个无效连接");
            }
            //没有空闲连接且当前连接小于允许最大值，若最大值为0，则不限制
        }else if(maxConnection == 0 || numTotal < maxConnection){
            connection = newConnection();
            numTotal++;
        }

        if(connection != null){
            numActive++;
        }

        return connection;
    }

    //获取一个可用连接,并加上等待时间限制，时间为毫秒
    public Connection getConnection(long timeout) {
        long startTime = new Date().getTime();
        Connection connection = null;
        while((connection = getConnection()) == null){
            try{
                //20毫秒执行一次
                Thread.sleep(20);
            } catch (Exception e) {
                e.printStackTrace();
            }

            if((new Date().getTime() - startTime) >= timeout){
                return null;//如果超时，则返回
            }
        }
        return connection;
    }

    public void freeConnection(Connection con) {
        freeConnections.addElement(con);
        numFree++;
        numActive--;
//        notifyAll();//解锁
    }

    public int getNumFree() {
        return numFree;
    }

    public int getNumActive() {
        return numActive;
    }

    //释放所有连接
    public synchronized void release() {
        try {
            Enumeration allConnections = freeConnections.elements();
            while (allConnections.hasMoreElements()) {
                Connection conn = (Connection) allConnections.nextElement();
                try {
                    conn.close();
                    numFree--;
                } catch (Exception e) {
                    System.out.println("无法关闭连接池中的连接");
                }
            }
            freeConnections.removeAllElements();
            numTotal=0;
        } catch (Exception e) {
            System.out.println("释放失败!");
        } finally {
            //卸载驱动
            super.release();
        }

    }
}
